options(scipen=10)
pacman::p_load(latex2exp,Matrix,dplyr,tidyr,ggplot2,caTools,plotly)
# rm(list=ls(all=TRUE))
load("data/tf4.rdata")B$Buy : 預期再購機率 Re-Purchase ProbabilityB$Rev : 預期購買金額 Expected Revenue Contributionpar(mfrow=c(1,2), cex=0.8)
hist(B$Buy)
hist(log(B$Rev,10))B %>% ggplot(aes(x=age,y=Rev)) +
geom_boxplot() + scale_y_log10()group_by(B,age) %>%
summarise(n=n(), Buy=mean(Buy), Rev=mean(Rev)) %>%
ggplot(aes(Buy,Rev,size=n,label=age)) +
geom_point(alpha=0.5,color='gold') +
geom_text(size=4) +
labs(title="Age Group Statistics (size: no. customers)") +
scale_size(range=c(4,20)) + theme_bw() -> p
ggplotly(p)🌻
🌻 我們可以用R內建的邏輯式函數(plogis())來模擬S曲線
定義、畫出效用函數
由於c()是一個常用的R內建功能,以下我們用x代表成本
\[\Delta P = f(x|m,b,a) = m \cdot
Logis(\frac{10(x - b)}{a})\]
# 自由設 x, m0, b0, a0
DP = function(x,m0,b0,a0) {m0*plogis((10/a0)*(x-b0))}
par(mar=c(4,4,2,1),cex=0.7)
curve(DP(x,m=0.20,b=30,a=40), 0, 60, lwd=2, ylim=c(0, 0.25),
main="F( x | m=0.2, b=30, a=40 )", ylab="delta P")
abline(h=seq(0,0.2,0.05),v=seq(0,60,5),col='lightgrey',lty=2)期望(淨)報償的算法: \[\hat{R}(x) = \left\{\begin{matrix} \Delta P \cdot M \cdot margin - x & , & P + \Delta P \leq 1\\ (1-P) \cdot M \cdot margin - x & , & else \end{matrix}\right.\]
估計毛利率(margin)
# load(data/tf0.rdata)
# group_by(Z0, age) %>% summarise(sum(price)/sum(cost) - 1)
margin = 0.17 # assume margin = 0.17估計預期報償
m=0.2; b=25; a=40; x=30
dp = pmin(1-B$Buy, DP(x,m,b,a))
eR = dp*B$Rev*margin - x
hist(eR,main="預期報償分佈",xlab="預期報償",ylab="顧客數")🌻 有多少顧客的預期報償大於零?
sum(eR>0) # 6679## [1] 6679
🌻 如果我們針對所有顧客做促銷,預期報償將是?
sum(eR) # -202435## [1] -202435.4
🌻 如果我們針對預期報償大於零顧客做促銷,預期報償將是?
sum(eR[eR>0]) # 80359## [1] 80358.8
m=0.2; b=25; a=40; X = seq(10,45,1)
df = sapply(X, function(x) {
dp = pmin(DP(x,m,b,a),1-B$Buy)
eR = dp*B$Rev*margin - x
c(x=x, eReturn=sum(eR), N=sum(eR > 0), eReturn2=sum(eR[eR > 0]))
}) %>% t %>% data.frame %>%
gather('key','value',-x)
df %>% ggplot(aes(x=x, y=value, col=key)) +
geom_hline(yintercept=0,linetype='dashed') +
geom_line(size=1.5,alpha=0.5) +
facet_wrap(~key,ncol=1,scales='free_y') + theme_bw()# gather : 以 x 為主,轉 df 表格
# scales='free_y' : 根據每個面板中的數據來縮放 y 軸範圍
# gather()
# 第一个参数放的是原数据,数据类型要是一个数据框
# 下面传一个键值对,名字是自己起的,这两个值是做新转换成的二维表的表头,即两个变量名
# 第四个是选中要转置的列,这个参数不写的话就默认全部转置
# 后面还可以加可选参数 na.rm,如果na.rm = TRUE,那么将会在新表中去除原表中的缺失值(NA)
# https://blog.csdn.net/six66667/article/details/84888644
# 结果:行列转换过来了,第一个参数是原数据stu,二、三两个参数是键值对(性别,人数),第四个表示减去(除去grade列,就只转置剩下两列)# 先來張 4 個模型的 S 曲線
mm=c(0.20, 0.25, 0.15, 0.25)
bb=c( 25, 30, 15, 30)
aa=c( 40, 40, 30, 60)
X = seq(0,60,2)
do.call(rbind, lapply(1:length(mm), function(i) data.frame(
Inst=paste0('Inst',i), Cost=X,
Gain=DP(X,mm[i],bb[i],aa[i])
))) %>% data.frame %>%
ggplot(aes(x=Cost, y=Gain, col=Inst)) +
geom_line(size=1.5,alpha=0.5) + theme_bw() +
ggtitle("Prob. Function: f(x|m,b,a)")X = seq(10, 60, 1) # 成本範圍
# 這裡有 4 個模擬器,分別看
# eReturn : 對所有的人行銷的總預期收益
# eReturn2 : 只對期收益大於零的人做行銷的總預期收益
# N : 預期收益大於零的人數
# 再用 lapply rbind 4 個模擬器
df = do.call(rbind, lapply(1:length(mm), function(i) {
sapply(X, function(x) {
dp = pmin(1-B$Buy, DP(x,mm[i],bb[i],aa[i]))
eR = dp*B$Rev*margin - x
c(i=i, x=x, eR.ALL=sum(eR), N=sum(eR>0), eR.SEL=sum(eR[eR > 0]) )
}) %>% t %>% data.frame
}))
# vars :選擇變量 == select()
df %>%
mutate_at(vars(eR.ALL, eR.SEL), function(y) round(y/1000)) %>%
gather('key','value',-i,-x) %>%
mutate(Instrument = paste0('I',i)) %>%
ggplot(aes(x=x, y=value, col=Instrument)) +
geom_hline(yintercept=0, linetype='dashed', col='blue') +
geom_line(size=1.5,alpha=0.5) +
xlab('工具選項(成本)') + ylab('預期報償(K)') +
ggtitle('行銷工具優化','假設行銷工具的效果是其成本的函數') +
facet_wrap(~key,ncol=1,scales='free_y') + theme_bw() -> p
plotly::ggplotly(p)# eR.ALL=sum(eR),全做通常都會虧本
# eR.SEL : 挑正的做 : I2,預期淨收益最大,落在成本 40 處
# 預期(淨)營收 : 147 K (146568)
# N : 40元時,可對 8344 個人做每一個工具的最佳參數
# 利用這行指令,抓出所有模擬器的最佳解 : eR.SEL 最大 (挑正的做)
group_by(df, i) %>% top_n(1,eR.SEL)## # A tibble: 4 x 5
## # Groups: i [4]
## i x eR.ALL N eR.SEL
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 34 -215958. 7027 98033.
## 2 2 40 -194886. 8344 146568.
## 3 3 22 -49192. 10262 108802.
## 4 4 43 -305864. 6495 112184.
par(cex=0.7, mar=c(2,2,1,2))
table(B$age) %>% barplot
🗿 討論問題:
如果上述4組工具參數分別是某折價券對4個不同年齡族群的效果:
■
I1 : a24, a29
■ I2 : a34, a39
■ I3 : a44, a49
■
I4 : a54, a59, a64, a69
如果你可以在這4個年齡族群之中選擇行銷對象,你應該如何:
■
選擇行銷對象(N)?
■
設定折價券的面額(x)?
■
估計預期報償(eR.SEL)?
■ I1
:面額:34;對560人做;預期報償:6472
■ I2
:面額:40;對4083人做;預期報償:74282
■ I3
:面額:22;對3131人做;預期報償:34746
■ I4
:面額:43;對643人做;預期報償:9403
# 分別挑出4個不同年齡族群
ci = sapply(
list(c("a24","a29"),c("a34","a39"),
c("a44","a49"),c("a54","a59","a64","a69")),
function(v) B$age %in% v)
X = seq(10, 60, 1)
df = do.call(rbind, lapply(1:length(mm), function(i) {
sapply(X, function(x) {
dp = pmin(1- B$Buy[ ci[,i] ] , DP(x,mm[i],bb[i],aa[i]))
eR = dp* B$Rev[ ci[,i] ] *margin - x
c(i=i, x=x, eR.ALL=sum(eR), N=sum(eR>0), eR.SEL=sum(eR[eR > 0]) )
}) %>% t %>% data.frame
}))
group_by(df, i) %>% top_n(1,eR.SEL)## # A tibble: 4 x 5
## # Groups: i [4]
## i x eR.ALL N eR.SEL
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 34 -51966. 560 6472.
## 2 2 40 -29651. 4083 74282.
## 3 3 22 -4068. 3131 34746.
## 4 4 43 -84668. 643 9403.